package dai.samples.batch.rw;

import dai.samples.batch.entity.BatchEntity;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.database.JdbcCursorItemReader;
import org.springframework.batch.item.database.JdbcPagingItemReader;
import org.springframework.batch.item.database.Order;
import org.springframework.batch.item.database.builder.JdbcCursorItemReaderBuilder;
import org.springframework.batch.item.database.builder.JdbcPagingItemReaderBuilder;
import org.springframework.batch.item.database.support.MySqlPagingQueryProvider;
import org.springframework.batch.item.file.FlatFileItemReader;
import org.springframework.batch.item.file.MultiResourceItemReader;
import org.springframework.batch.item.file.ResourceAwareItemReaderItemStream;
import org.springframework.batch.item.file.builder.MultiResourceItemReaderBuilder;
import org.springframework.batch.item.file.mapping.DefaultLineMapper;
import org.springframework.batch.item.file.mapping.FieldSetMapper;
import org.springframework.batch.item.file.transform.DelimitedLineTokenizer;
import org.springframework.batch.item.json.JacksonJsonObjectReader;
import org.springframework.batch.item.json.builder.JsonItemReaderBuilder;
import org.springframework.batch.item.xml.StaxEventItemReader;
import org.springframework.batch.item.xml.builder.StaxEventItemReaderBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.oxm.xstream.XStreamMarshaller;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

/**
 * 读取数据的配置
 */
@Configuration
public class ReadConfig {

    @Autowired
    DataSource dataSource;

    /************************读取文件数据************************/

    /**
     * 读取行数据
     * @return
     */
    @Bean(name = "itemLineReader")
    public FlatFileItemReader<BatchEntity> itemLineReader() throws Exception {
        // 设置文件地址
        FlatFileItemReader<BatchEntity> reader = new FlatFileItemReader<BatchEntity>();
        reader.setResource(new ClassPathResource("rw/batchJobLine.txt"));
        reader.setName("itemLineReader");
        // 设置是否跳过行
        // reader.setLinesToSkip(5);
        /*定义每一条记录 转换java实体类*/
        DefaultLineMapper<BatchEntity> lineMapper = new DefaultLineMapper<BatchEntity>();

        // delimiter 参数定义分隔符
        DelimitedLineTokenizer tokenizer = new DelimitedLineTokenizer();
        tokenizer.setNames("entityId,age,firstName,isAdult,lastName".split(","));
        // 设置分隔符
        // tokenizer.setDelimiter(",");
        lineMapper.setLineTokenizer(tokenizer);
        lineMapper.setFieldSetMapper(fieldSetMapper());
        reader.setLineMapper(lineMapper);
        reader.afterPropertiesSet();
        return reader;
    }

    /**
     * 读取JSON数据
     * @return
     */
    @Bean(name = "itemJsonReader")
    public ItemReader<BatchEntity> itemJsonReader() {
        return new JsonItemReaderBuilder<BatchEntity>()
                .jsonObjectReader(new JacksonJsonObjectReader<>(BatchEntity.class))
                .resource(new ClassPathResource("rw/batchJobJson.json"))
                .name("batchJobReader")
                .build();
    }

    /**
     * XML读取数据
     * @return
     */
    @Bean(name = "itemXmlReader")
    public StaxEventItemReader<BatchEntity> itemXmlReader() {
        XStreamMarshaller unmarshaller = new XStreamMarshaller();
        Map<String,Class> map = new HashMap<>();
        map.put("data", BatchEntity.class);
        unmarshaller.setAliases(map);
        return new StaxEventItemReaderBuilder<BatchEntity>()
                .resource(new ClassPathResource("rw/batchJobXml.xml"))
                .addFragmentRootElements("data")
                .unmarshaller(unmarshaller)
                .name("itemXmlReader")
                .build();
    }

    /**
     * 读取多个文件
     * @return
     */
    @Bean(name = "itemFileReader")
    public MultiResourceItemReader itemFileReader() throws Exception {
        MultiResourceItemReaderBuilder<BatchEntity> rwfile =
                new MultiResourceItemReaderBuilder<BatchEntity>()
                .resources(new ClassPathResource("rwfile/batchJobLine.txt"),
                           new ClassPathResource("rwfile/batchJobLine2.txt"));
        rwfile.delegate(delegate());
        rwfile.name("itemFileReader");
        return rwfile.build();
    }

    private ResourceAwareItemReaderItemStream<? extends BatchEntity> delegate() throws Exception {
        // 设置文件地址
        FlatFileItemReader<BatchEntity> reader = new FlatFileItemReader<BatchEntity>();
        reader.setResource(new ClassPathResource("rw/batchJobLine.txt"));
        reader.setName("delegateReader");
        // 设置是否跳过行
        // reader.setLinesToSkip(5);
        /*定义每一条记录 转换java实体类*/
        DefaultLineMapper<BatchEntity> lineMapper = new DefaultLineMapper<BatchEntity>();

        // delimiter 参数定义分隔符
        DelimitedLineTokenizer tokenizer = new DelimitedLineTokenizer();
        tokenizer.setNames("entityId,age,firstName,isAdult,lastName".split(","));
        // 设置分隔符
        // tokenizer.setDelimiter(",");
        lineMapper.setLineTokenizer(tokenizer);
        lineMapper.setFieldSetMapper(fieldSetMapper());
        reader.setLineMapper(lineMapper);
        reader.afterPropertiesSet();
        return reader;
    }


    /************************从数据库中读物文件************************/


    /***
     * 使用JDBC读取数据
     * @return
     */
    @Bean(name = "itemJdbcReader")
    public JdbcPagingItemReader<BatchEntity> itemJdbcReader() {
        // 查询SQL
        MySqlPagingQueryProvider queryProvider = new MySqlPagingQueryProvider();
        queryProvider.setSelectClause("entity_id,age,first_name,full_name,hello_message,is_adult,last_name");
        queryProvider.setFromClause("from batch_entity");
        // 设置排序
        Map<String, Order> sortKeys = new HashMap<String, Order>();
        sortKeys.put("age", Order.ASCENDING);
        queryProvider.setSortKeys(sortKeys);

        return new JdbcPagingItemReaderBuilder<BatchEntity>()
                .dataSource(dataSource)
                .fetchSize(5)
                .rowMapper(new BeanPropertyRowMapper<>(BatchEntity.class))
                .queryProvider(queryProvider)
                .name("itemJdbcReader")
                .build();
    }

    /***
     * 使用JDBC游标读取数据
     * @return
     */
    @Bean(name = "itemJdbcCursorReader")
    public JdbcCursorItemReader<BatchEntity> itemJdbcCursorReader() {
        return new JdbcCursorItemReaderBuilder<BatchEntity>()
                .dataSource(dataSource)
                .fetchSize(5)
                .rowMapper(new BeanPropertyRowMapper<>(BatchEntity.class))
                .sql("select entity_id,age,first_name,full_name,hello_message,is_adult,last_name from batch_entity")
                .name("itemJdbcCursorReader")
                .build();
    }



    private FieldSetMapper fieldSetMapper() {
        return fieldSet -> new BatchEntity(
                fieldSet.readString("entityId"),
                fieldSet.readInt("age"),
                fieldSet.readString("firstName"),
                fieldSet.readBoolean("isAdult"),
                fieldSet.readString("lastName")
        );

        /*return fieldSet -> new BatchEntity(
                fieldSet.readString(0),
                fieldSet.readInt(1),
                fieldSet.readString(2),
                fieldSet.readBoolean(3),
                fieldSet.readString(4)
        );*/
    }
}
